import { Vector3, Scene, PerspectiveCamera, WebGLRenderer, Mesh } from 'three';
import MouseController from '../controller/MouseController';
import Config from '../Config';
import { ArcballControls } from 'three/examples/jsm/controls/ArcballControls';
import MapController from '../controller/MapController';

export default class GlobalScene extends Scene {
    public static instance: GlobalScene;
    private camera: PerspectiveCamera;
    private mouseContorl: MouseController;
    private mapController: MapController;

    public constructor() {
        super();
        GlobalScene.instance = this;
    }

    public createScene() {
        // 创建相机
        this.camera = new PerspectiveCamera(75, window.innerWidth / window.innerHeight, 400, Config.Ellipsoid.radii.x * 10);
        // camera.position.z = Config.Ellipsoid.radii.x * 2;
        let cameraY = Config.Ellipsoid.radii.x * 2; //6378137 + 5; //12800380.575865034; //
        this.camera.position.set(0, cameraY, 0);

        this.camera.up.set(0, 0, 1);
        this.camera.lookAt(new Vector3(0, 0, 0));

        // 强制更新相机的视图矩阵
        this.camera.updateMatrixWorld();

        this.add(this.camera);

        // 创建渲染器
        const renderer = new WebGLRenderer();
        renderer.setSize(window.innerWidth, window.innerHeight);
        document.body.appendChild(renderer.domElement);

        this.mapController = new MapController(this.camera);

        this.mouseContorl = new MouseController(this.camera, renderer.domElement, this.mapController);
        this.updateCameraNear();
       
        this.mouseContorl.loadTiles();

        let self = this;
        // 渲染循环
        function animate() {
            requestAnimationFrame(animate);
            // cameraControl.update();

            // 分发动画事件
            self.dispatchEvent({ type: 'render' });

            renderer.render(self, self.camera);
        }

        animate();

        return this;
    }

    public updateCameraNear() {
        let sightPoint = this.mouseContorl.getSightPoint(this.camera);
        let sightDirection = this.camera.position.clone().sub(sightPoint);
        let length = sightDirection.length();
        let cameraNear;
        if(length < 1000){
            cameraNear = length / 10;
        }else{
            cameraNear = length / 100;
        }

        if (cameraNear < 1) {
            cameraNear = 1;
        }
        this.camera.near = cameraNear;

        let ellipsoidCenter = Config.Ellipsoid.center;
        let cameerFar = this.camera.position.distanceTo(ellipsoidCenter);
        this.camera.far = cameerFar;
        this.camera.updateProjectionMatrix();
    }

    public testTiles(){
        let sightPoint = this.mouseContorl.getSightPoint(this.camera);
        let mapLevel = this.mapController.computeLevel(sightPoint);
        let visibleTileStrSet = this.mapController.computeVisibleTiles(sightPoint, mapLevel);
        this.mapController.loadTiles(visibleTileStrSet);
    }

    public testTilesWithZoom(){
        let sightPoint = this.mouseContorl.getSightPoint(this.camera);
        let mapLevel = this.mapController.computeLevel(sightPoint);
        let visibleTileStrSet = this.mapController.computeVisibleTiles(sightPoint, mapLevel);
        this.mapController.loadZoomTiles(visibleTileStrSet, 'down', mapLevel);
    }

    private tileArray = []
    public addTile(tileMesh: Mesh){
        this.add(tileMesh);
        // this.tileArray.push(tileMesh);
    }

    // public removeAllTiles(){
    //     this.tileArray.forEach(tileMesh => {
    //         this.remove(tileMesh);
    //     });
    //     this.tileArray = [];
    // }
}
